package com.example.braden.answergame.component;

import com.example.braden.answergame.BuildConfig;
import com.example.braden.answergame.base.BaseApplication;
import com.example.braden.answergame.base.BaseResult;
import com.example.braden.answergame.common.Constant;
import com.example.braden.answergame.common.LogUtils;
import com.example.braden.answergame.common.utils.CommonUtil;
import com.example.braden.answergame.common.utils.NetUtil;
import com.example.braden.answergame.common.utils.RxUtil;
import com.example.braden.answergame.common.utils.ToastUtil;
import com.example.braden.answergame.modules.main.domain.MyPropEntity;
import com.example.braden.answergame.modules.main.domain.ReadyEntity;
import com.example.braden.answergame.modules.main.domain.UsePropEntity;

import io.reactivex.Observable;
import io.reactivex.functions.Consumer;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by braden on 2018/1/3.
 */

public class RetrofitSingleton {
    private static ApiInterface sApiService = null;
    private static Retrofit sRetrofit = null;
    private static OkHttpClient sOkHttpClient = null;

    private void init() {
        initOkHttp();
        initRetrofit();
        sApiService = sRetrofit.create(ApiInterface.class);
    }

    private RetrofitSingleton() {
        init();
    }

    public static RetrofitSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final RetrofitSingleton INSTANCE = new RetrofitSingleton();
    }

    private static void initOkHttp() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        File cacheFile = new File(Constant.NET_CACHE);
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
        Interceptor cacheInterceptor = chain -> {
            //Request request = chain.request();
            //if (!NetUtil.isNetworkConnected(BaseApplication.getAppContext())) {
            //request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE)
            //        //.addHeader("appkey", Constant.APP_KEY)
            //        //.addHeader("version",
            //        //        CommonUtil.getVerName(BaseApplication.getAppContext()))
            //        .build();
            //FormBody.Builder bodyBuilder = new FormBody.Builder();
            //FormBody formBody = (FormBody) request.body();
            ////把原来的参数添加到新的构造器，（因为没找到直接添加，所以就new新的）
            //for (int i = 0; i < formBody.size(); i++) {
            //    bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
            //}
            RequestBody body = new FormBody.Builder().add("appkey", Constant.APP_KEY)
                    .add("version", CommonUtil.getVerName(BaseApplication.getAppContext()))
                    .build();
            Request request = chain.request().newBuilder().post(body).build();
            //}
            //Response response = chain.proceed(request);
            //Response.Builder newBuilder = response.newBuilder();
            //if (NetUtil.isNetworkConnected(BaseApplication.getAppContext())) {
            //    int maxAge = 0;
            //    // 有网络时 设置缓存超时时间0个小时
            //    newBuilder.header("Cache-Control", "public, max-age=" + maxAge);
            //} else {
            //    // 无网络时，设置超时为4周
            //    int maxStale = 60 * 60 * 24 * 28;
            //    newBuilder.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale);
            //}
            //return newBuilder.build();
            return chain.proceed(request);
        };
        builder.cache(cache).addInterceptor(cacheInterceptor);
        if (BuildConfig.DEBUG) {
            //builder.addNetworkInterceptor(new StethoInterceptor());
        }
        //设置超时
        builder.connectTimeout(15, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        //错误重连
        builder.retryOnConnectionFailure(true);
        sOkHttpClient = builder.build();
    }

    private void initRetrofit() {
        sRetrofit = new Retrofit.Builder().baseUrl(Constant.getBaseUrl())
                .client(sOkHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    /**
     * 获取双方用户信息
     */
    public Observable<ReadyEntity> fetchReady(String rid, String openId) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign =
                CommonUtil.getSigns("rid=" + rid, "openid=" + openId, "timestamp=" + timestamp);
        LogUtils.e("signs:" + sign);
        return sApiService.mReadyAPI(rid, openId, sign, timestamp)
                .flatMap(Observable::just)
                .doOnError(RetrofitSingleton::disposeFailureInfo)
                .compose(RxUtil.io());
    }

    /**
     * 上报答案
     */
    public Observable<BaseResult> fetchAnswer(String rid, String openId, int qid, int answer) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign =
                CommonUtil.getSigns("rid=" + rid, "openid=" + openId, "timestamp=" + timestamp,
                        "qid=" + qid, "answer=" + answer);
        return sApiService.answerQustion(rid, openId, qid, answer, sign, timestamp)
                .doOnError(RetrofitSingleton::disposeFailureInfo)
                .compose(RxUtil.io());
    }

    /**
     * 使用道具
     *
     * @param rid      房间id
     * @param openId   用户openid
     * @param qid      题目id
     * @param prop_key 道具id
     * @param is_use   是否使用了道具 0未使用，1已使用
     */
    public Observable<UsePropEntity> useProp(String rid, String openId, int qid, String prop_key,
                                             int is_use) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign =
                CommonUtil.getSigns("rid=" + rid, "openid=" + openId, "timestamp=" + timestamp,
                        "qid=" + qid, "prop_id=" + prop_key, "is_use=" + is_use);
        LogUtils.e("sign:" + sign);
        return sApiService.mUseProp(rid, openId, qid, prop_key, sign, timestamp, is_use)
                .doOnError(RetrofitSingleton::disposeFailureInfo)
                .compose(RxUtil.io());
    }

    /**
     * 开始游戏
     */
    public Observable<BaseResult> startGame(String rid, String openId) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign =
                CommonUtil.getSigns("rid=" + rid, "openid=" + openId, "timestamp=" + timestamp);
        return sApiService.mStartGameAPI(rid, openId, sign, timestamp)
                .doOnError(RetrofitSingleton::disposeFailureInfo)
                .compose(RxUtil.io());
    }

    /**
     * 退出游戏
     */
    public Observable<BaseResult> quitGame(String rid, String openid) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String sign =
                CommonUtil.getSigns("rid=" + rid, "openid=" + openid, "timestamp=" + timestamp);
        return sApiService.mQuitGame(rid, openid, sign, timestamp)
                .doOnError(RetrofitSingleton::disposeFailureInfo)
                .compose(RxUtil.io());
    }

    private static Consumer<Throwable> disposeFailureInfo(Throwable t) {
        return throwable -> {
            ToastUtil.showShort("请检查网络");
            LogUtils.e("throwable:" + t.toString());
        };
    }
}
